% !Mode:: "TeX:UTF-8"
% 上面这一行使得在windows环境中打开可以正常显示
\input{./common/head.tex}

\begin{document}
\begin{CJK}{UTF8}{song}
\title{TEP文档结构和关键词说明}
\author{张頔 翻译作品\\http://tinyos-cn.googlecode.com\\http://blog.csdn.net/zhangdi\_china}
\maketitle

\begin{tabular}{|l|l|}
  \hline
    TEP:		& 2 \\
    Group:		& Core Working Group\\
    Type:		& Best Current Practice\\
    Status:		& Final\\
    TinyOS-Version:	& 2.x\\
    Author:		& Vlado Handziski, Joseph Polastre, Jan-Hinrich Hauer,\\
			& Cory Sharp, Adam Wolisz, David Culler, David Gays\\
    Translator:		& Zhang Di\\
  \hline
\end{tabular}

\begin{quote}
  This document specifies a Best Current Practices for the TinyOS Community,
  and requests discussion and suggestions for improvements. The distribution
  of the memo is unlimited, provided that the header information and this note
  are preserved. Parts of this document are taken verbatim from the [HAA2005] 
  paper that is under IEEE copyright and from the [T2\_TR] technical report. 
  This memo is in full compliance with [TEP1].
\end{quote}

\begin{abstract}
  本TEP文档描述了TinyOS 2.0的硬件抽象架构(HAA)，后者用于平衡 重用/可移植性 和
  效率/性能优化 之间的矛盾。TinyOS采用的三层硬件抽象模型渐进地将底层硬件平台适配到
  精心挑选的平台无关接口，这些接口是内核和应用层之间的桥梁。
  当性能需求甚于对跨平台需求时，应用程序可以通过第二层抽象模型充分发掘某特定平台的能量。
\end{abstract}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{简介}
  在操作系统中引入硬件抽象策略，已经被证明对于应用程序开发是行之有效的。
  隐藏底层硬件细节可以简化编码、提高可移植性。但追求硬件抽象与效率和功耗是一对矛盾
  ，特别是在传感器网络领域中。

  这就需要一种精心定义的硬件抽象架构，用以打破上述矛盾。其挑战在于找到一种合适的分层方式，
  使得TinyOS组件既可以获得可移植性，又能够按需加强硬件访问能力从而保持能效。
  \footnote{ZhangDi：原文句子太长}
  本TEP文档提出了一种应用于TinyOS 2.0的有效的三层硬件抽象结构（HAA）。
  顶层的抽象提供了平台无关的接口以保证可移植性。中间层以效率为目标，
  提供了丰富的硬件相关的接口。底层提供了基本的硬件寄存器和中断的访问接口。

  本TEP文档的其余部分描述了：
  \begin{itemize}
    \item HAA的细节及其所包含的三个不同的层；
    \item 选择抽象的层次的原则；
    \item 不同的硬件平台之间如何共享硬件抽象；
    \item CPU的硬件抽象层；
    \item 某些硬件抽象是如何变通地使用HAA架构的；
  \end{itemize}

  上述HAA结构是许多TinyOS2.0文献类TEP文档的架构基础(如[TEP101-103])。
  那些TEP文档关注于在这种抽象框架下某个硬件模块的实现。
  [TEP112]和[TEP115]是解释功耗管理的实现。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{架构}
  上述的分层结构把硬件的功能抽象成三个独立的组件层。每个抽象层都有明确定义的抽象任务，
  并且依赖于较低抽象层提供的接口。底层硬件的功能被渐进地适配到内核和应用层间的平台无关接口。
  自下而上，组件对硬件的依赖性渐小，开发人员在复用性上获得自由度也越大。
  \begin{lstlisting}
                 +-----------------------------+
                 |                             |
                 | Cross-platform applications |
                 |                             |
                 +--------------+--------------+
+-----------------+             |                 +-----------------+
|Platform-specific|             |                 |Platform-specific|
|  applications   |             |                 |  applications   |
+---+-------------+             |                 +-------------+---+
    |      Platform-independent | hardware interface            |
    |        +-------------+----+---+----+-------------+        |
    |        |             |             |             |        |
    |  +-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+  |
    |  |+----+----+| |+----+----+| |+----+----+| |+----+----+|  |
    |  ||         || ||         || ||         || ||  HIL 4  ||  |
    |  ||  HIL 1  || ||  HIL 2  || ||  HIL 3  || |+----+----+|  |
    |  ||         || |+----+----+| |+----+----+| |     |     |  |
    |  |+----+----+| |     |     | |     |     | |     |  +--+--+
    +--+--+  |     | |+----+----+| |     |     | |     |  |  |
       |  |  |     | ||         || |+----+----+| |+----+--+-+|
       |+-+--+----+| ||         || ||         || ||         ||
       ||         || ||  HAL 2  || ||         || ||         ||
       ||         || ||         || ||  HAL 3  || ||  HAL 4  ||
       ||  HAL 1  || |+----+----+| ||         || ||         ||
       ||         || |     |     | ||         || ||         ||
       ||         || |     |     | |+----+----+| |+----+----+|
       |+----+----+| |+----+----+| |     |     | |     |     |
       |     |     | ||         || |+----+----+| |     |     |
       |+----+----+| ||  HPL 2  || ||         || |+----+----+|
       ||  HPL 1  || ||         || ||  HPL 3  || ||  HPL 4  ||
       |+----+----+| |+----+----+| |+----+----+| |+----+----+|
       +-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+  
             |             |             |             |    `软硬件边界`
     *****************************************************************
      +------+-----+ +-----+-----+ +-----+-----+ +-----+-----+
      |HW Plat 1   | |HW Plat 2  | |HW Plat 3  | |HW Plat 4  |
      +------------+ +-----------+ +-----------+ +-----------+
        Fig.1: The proposed Hardware Abstraction Architecture
  \end{lstlisting}	\footnote{这图画得还能再难看点儿么~~}

  和其它的嵌入式操作系统[WindowsCE]的两层抽象结构不同，三层抽象结构提供了更多的灵活性。
  \footnote{Android}
  TinyOS把平台相关抽象和适配器分开，后者将前者升级或降级为当前的平台无关接口。
  为了追求极致性能，平台相关应用可以绕过HIL层，直接访问HAL层以充分利用硬件。

  本节的其它部分详述了每个组件层的设计细则。
  \subsection{硬件表示层(HPL)}
    硬件表示层(HPL)的组件是软硬件的分水岭。正如其名称所示，该层组件的主要任务
    就是用操作系统中原始概念“表示”硬件的功能。这些组件用惯常的方式来访问硬件，
    或者通过内存，或者通过端口映射IO。反之，硬件可以用触发中断的方式来请求服务。
    通过这些方式，HPL层把硬件错综复杂的细节隐藏起来，向上提供可读性好的接口(简单函数)。

    HPL组件应当(SHOULD)是无状态的，并且所导出的接口完全是决定于其抽象的硬件。
    \footnote{ZhangDi：所谓无状态，就是指接口的输出完全取决于当前的硬件的状态，软件并不记忆状态。
	      学过数字电路的：如果硬件算输入，那么这层的软件部分可以算作“纯组合逻辑”。}
    这种和硬件紧密耦合的方式使得HPL层的设计没有什么自由度可言。纵然HPL组件有着和硬件一样的独特性，
    但是它们也有类似的统一结构。为了便于和其它部分集成，每个HPL组件都应当(SHOULD)具有：
    \begin{itemize}
      \item 用以初始化、启动和停止硬件模块的命令。在功耗管理策略中这些是必须的；
      \item 硬件控制寄存器的存取方法(get/set)；
      \item 常用标志位的置位/测试命令。这些命令应当有靠谱的名字；
      \item 使能/关闭硬件中断的命令；
      \item 硬件中断的服务例程；
    \end{itemize}

    HPL组件的中断服务例程只进行对实时性要求最严苛的操作（复制单个值，清除标志位，等等），
    操作的其余部分留给高层组件，因为后者可以获得更多的系统状态信息。

    上述HPL结构简化了硬件操作。相比使用编译器库中的头文件里天书般的宏定义和寄存器名，
    （那些东西经常得在编译器的函数库中找来找去），程序员这回可以用他们熟悉的接口形式了。
    \footnote{找头文件，是挺2的}

    HPL除了提供最常用的操作序列之外，并没有提供大量的硬件抽象。尽管如此，它还是隐藏了
    大部分依赖于特定硬件的代码，并且为高层抽象组件的开发工作铺平了道路。高层抽象组件会
    用到同类硬件模块的不同HPL抽象。譬如，现有的传感器网络平台的微控制器一般都有两个
    USART模块用于串行通信。它们的功能相同但是在寄存器和中断向量的细节上略有不同。
    HPL组件可以用一致性接口屏蔽细微差别，以获得高层抽象的硬件无关性。
    程序员无需改变组件的实现段代码
    \footnote{ZhangDi：在TinyOS的基础语言nesC中，implementation有着特定的含义。
	      用nesC语言编写的模块，有规格段和实现段，组件之间用配件(configuration)相连接(wire)，
	      根据此处上下文，implementation一词，应当是指狭义的“实现段”。}
    ，
    仅通过改变连接(wire)就可以切换不同的USART模块。

  \subsection{硬件适配层(HAL)}
    适配层的组件是这个三层抽象结构的核心。它们使用HPL层提供的原始接口，构建出用以屏蔽硬件复杂性的抽象层，
    这里的复杂性源自硬件的自然使用方式
    \footnote{ZhangDi：这里的原文便很晦涩，略作说明：硬件刨到根是读写寄存器，
	      但是复杂外设的操作得通过一系列读写寄存器的行为来实现。
	      而这种系列的读写行为，一般情况下是“龙套”，此之为“源自硬件的自然使用方式”。
	      }
    \footnote{英文原文：They use the raw interfaces provided by the HPL components
		      to build useful abstractions hiding the complexity naturally 
		      associated with the use of hardware resources.
	      }
    。
    和HPL层组件不同，HAL层可以维护状态量，这些状态量可以用于仲裁和资源控制。

    在传感器网络领域中，效率是很重要的，所以HAL层的抽象按照硬件功能和不同的硬件平台分门别类。
    HAL层并不提供屏蔽不同类型硬件之间区别的泛型模型，而是保留对资源的使用效率的同时，
    尽力提供对硬件的最佳抽象以简化应用程序开发的流程
    \footnote{ZhangDi：这是TinyOS的设备驱动模型的特点}
    。
    譬如，和现代操作系统对所有的设备都提供统一的“文件”抽象不同，我们按照功能划分提供了丰富的定制接口，
    如Alarm，ADC通道，EEPROM等。根据具体模型的不同，HAL层组件应当(SHOULD)提供用以访问这些抽象模型的
    丰富的定制化的接口，而不是通过使用不堪重负的窄接口命令隐藏底层细节
    \footnote{对比Linux字符设备驱动模型就可以很清楚地理解这里所想表达的意思。
	      在Linux里，一切设备都被统一到文件抽象模型上。}
    。
    上述策略使得在编译时可以更有效地检查抽象接口的使用错误。

  \subsection{硬件接口层(HIL)}
    三层硬件抽象结构的最后一层由HIL层的组件构成。
    HIL层组件把HAL层提供的特定平台抽象转化成平台无关接口，后者用来编写跨平台应用。
    由于这些接口把底层硬件隐藏在平台无关抽象之下，应用开发得到了简化。
    为了更好地上述目的，这些API接口应当(SHOULD)反映出传感器网络应用的对硬件的典型需求。

    HIL层组件的复杂性取决于抽象目标和硬件能力之间的距离。
    当底层硬件的能力超出当前的API准则时，HIL层就把HAL层的平台相关接口裁减到标准接口。
    当底层的硬件能力不足时，HIL层就需要用软件来模拟硬件无法直接提供的功能。
    当一个新的更强大的平台被引入到系统里，当前的API就面临着被打破的压力。
    当性能需求甚于兼容性需求时，就会通过跨越式地发布新HAL层模型的方式，来提供经过调整的API接口。
    平台无关接口的变革会迫使代码维护者重写相应的HIL层组件。
    新引入平台的HIL会很简单，因为它的API规范和它底层的HAL层抽象关联紧密。
    另一方面来说，原有平台的软件升级工作会带来一些开销。   
    \footnote{意思很简单，发布新接口，当然是为了新平台。所以新平台编程当然容易。
	      老平台估计都快靠边站了，保证对它的兼容性当然要费些劲。}

    既然我们制定了HIL层接口根据新平台的演进策略，我们就必须确定软件模拟何时无法维持。
    有鉴于此，我们引入了HIL层接口的版本策略。通过给每一次迭代的HIL层接口指定版本号的方法，
    我们可以通过针对某个早先版本接口开发应用程序的方式去兼容早先的硬件设备。
    因为传感器网络的应用有可能一次部署经年运行，所以这点显得尤为重要。
    某个HIL版本也可以(MAY)有分支版本，以提供多种不同层面上的功能。

\section{联合不同层次的抽象}
  HIL和HAL为应用程序提供两个层次的抽象，这意味着应用程序和系统库的不同部分可以平行地从这个
  两个层次访问硬件资源。

  例如，TinyOS 2.0中的标准程序Oscilloscope使用ADC从传感器获取若干数据、构建消息帧并通过
  射频模块发送。出于跨平台兼容性的目的，该应用程序使用标准Read接口，该接口由ADC的HIL层提供
  ，并由连接(wired to)其上的DemoSensorC转接(温度传感器封装即如此)。当采集到足够的样本后，
  应用程序将消息帧传递给网络协议栈。协议栈的MAC层进行空闲信道评估以确定何时可以安全发送信息，
  这个过程同样可能涉及ADC采样(对RSSI信号)。因为临近数据点的相关性，这种操作的实时性要求很强，
  所以MAC层的设计者就可能直接使用HAL层提供的接口，因为这一层提供了更精细的控制能力。
  下图(Fig.2)展示了MSP430处理器的ADC协议栈是如何同时构建在HIL层和HAL层上的。
  \begin{lstlisting}
        +--------------------------------+
        |               APP              |
        +-+----------------------------+-+
          |                            |
         Read                         Send
          |                            |
          |                            |
+---------+----------+         +-------+--------+
|   DemoSensorC /    |         |                |
|   TemperatureC     |         | ActiveMessageC |
+---------+----------+         |                |
          |                    +-------+--------+
         Read                          |
          |                            |
          |                    +-------+--------+
+---------+----------+         |                |
| HIL:   AdcC        |         |                |
+---------+----------+         |  TDA5250       |
          |                    |                |
          |                    |  Radio Stack   |
          |                    |                |
          |                    +-------+--------+
          |                            |
          |     +----------------------+
          |     |
  Msp430Adc12SingleChannel
          |     |
          |     |
+---------+-----+----+
| HAL: Msp430Adc12C  |
+--------------------+
Fig.2: Accessing the MSP430 ADC hardware abstraction
                via *HIL* and *HAL* in parallel
  \end{lstlisting}

  为了支持这种垂直层次上的灵活性，ADC的HAL层包含了更复杂的资源仲裁和控制功能[TEP108]，
  以保证HPL层导出的资源可以被安全地共享访问。

\section{水平分解}
  除了HAA结构的垂直分解，水平分解也可以提升硬件抽象在不同平台间的可重用性。
  基于此目的，TinyOS2.x引入了“芯片抽象”(chips)的概念。“芯片抽象”是针对芯片自身的抽象，
  如MCU，射频收发器，Flash等。每个芯片的抽象分解遵循HAA模型，在最顶层组件提供HIL层接口。
  于是，整个软件平台可以用胶粘逻辑和不同芯片组件进行构建，如下图所示：
  \begin{lstlisting}
    +----------------------------------------------------+
    | AppC                                               |
    | /Application Component/                            |
    +------+--------------------------------------+------+
           |                                      |
           |Millisecond Timer                     | Communication
    +------+------+                     +---------+------+
    | TimerMilliC |                     | ActiveMessageC |
    |             |                     |                |
    | /Platform   |                     | /Platform      |
    |  Component/ |                     | Component/     |
    +------+------+                     +---------+------+
           |                                      |
    +------+------+                        +------+------+
    |             | 32kHz Timer            |             |
    |             |    +--------------+    |             |
    | Atmega128   |    | CC2420AlarmC |    | CC2420      |
    |             +----+              +----+             |
    | Timer Stack |    | /Platform    |    | Radio Stack |
    |             |    |  Component/  |    |             |
    | /Chip       |    +--------------+    | /Chip       |
    |  Component/ |                        |  Component/ |
    +-------------+                        +-------------+



Fig.3: The CC2420 software depends on a physical and dedicated
timer. The micaZ platform code maps this to a specific Atmega128
timer.
  \end{lstlisting}

  某些硬件模块通过总线的方式连接到微控制器上，如：SPI，I2C，UART总线。为了在不同平台
  之间共享硬件驱动程序，这个问题必须得到解决。显而易见，最具移植性和重用性的方法是类似
  NetBSD[netBSD]里的通用总线抽象结构。这个模型把不同的总线协议抽象到泛型总线访问模式。
  操作系统通过这种方式把芯片的抽象和互联的抽象解耦。在这种策略下，就有可能把同一芯片抽象
  应用于不同的互联协议(不同平台的互联协议)。但是，这种归一化的实现带来了很大的性能损失。
  在桌面操作系统上这样做也许是可以接受的，但它决不是传感器网络这类特定应用的最佳选择。

  TinyOS2.0退而求其次\footnote{TinyOS 2.0 takes a less generic approach}，
  它在HIL层分别为诸如I2C、SPI、UART和pin-IO的互联方式提供MCU无关的抽象。这种独到的方式
  使开发者可以针对不同协议进行优化，比如SPI抽象无需考虑设备地址而I2C抽象就需要。不仅如此，
  开发者可以选择直接使用芯片相关的HAL层组件，更精细地利用特定硬件的配置功能以提升性能。

  TinyOS2.0的总线抽象，配合以低层IO抽象和中断抽象(参见[TEP117])，使得针对某一特定芯片
  的抽象可以复用在任何支持相应所需总线的平台。举例来所，CC2420的射频模块就可以用在Telos
  和micaZ平台上，因为MSP430和Atmega128的串行通信模块都支持一致的SPI总线抽象。

  在平台之间共享芯片抽象会导致资源冲突问题
  (当多个芯片连接在同一总线时\footnote{TODO:此处文字尚需推敲})。
  在micaZ平台上CC2420独占SPI总线，而在Telos平台上CC2420和Flash芯片共享SPI总线。
  为了解决这类冲突问题，[TEP108]引入了资源预分配机制
  \footnote{resource reservation mechanism}
  ：
  每个使用总线协议的芯片抽象都必须(MUST)使用Resource接口获得总线的访问权。
  这样一来，挂在总线上的芯片既可以单独使用，也可以并行不悖地使用。
  \footnote{最后一句话随手一译，不甚准确~~}

\section{CPU抽象}
  在TinyOS中，处理器核心\footnote{ZhangDi：应该是不同指令集架构的一致性抽象}
  的一致性抽象用nesC/C语言和GCC编译器搞定。
  例如，和编译器一并发布的标准库函数包含了必须的启动代码和初始化全局变量、栈指针
  和中断向量表的过程。操作系统可以不必处理这些任务。为了更好地完成统一抽象任务，
  TinyOS提供了通用的结构用以声明可重入/非重入的中断服务例程和关键代码段。

  目前HAA并没有用来对不同的CPU进行抽象。对于目前支持的MCU来说，相应的编译器和底层IO就够了。
  尽管如此，如果未来有了需要TinyOS支持的新架构的内核，这部分的硬件抽象需要清晰定义。
  \footnote{ZhangDi：我当年看这东西的时候，主要的平台是MSP430和ATMegal128。
	    这次大概扫过去，支持的东西不少。好像还支持cotex-m体系。}
\section{HIL层对齐}
  \footnote{ZhangDi：对齐提法不好，我还没有想出合适的词}

  虽然HAA的三层架构要求HIL层提供完全不依赖于硬件的接口（强硬件接口层），
  但有些抽象只能部分满足这个目标（弱硬件接口层）。本节介绍了用以描述在不
  同级别上满足HIL层硬件无关性的术语。以下是两个基本的提法：
  \begin{itemize}
    \item 平台定义(platform-defined)的X：X定义在所有平台上，但是实现方式有所不同；
    \item 特定平台的(platform-specific)X：X定义在某个特定平台上；
  \end{itemize}

  \subsection{强硬件接口层}
    强硬件接口层意味代码可以在所有的实现中有着相同的行为方式。
    当然这也是HIL层的本意。如定时器（TimerMilliC）[TEP102]，发光二极管（LedsC），
    主动消息（ActiveMessageC，在不使用元数据的情况下）[TEP106]，
    传感器封装（DemoSensorC）[TEP109]，存储器[TEP103]。
    强硬件接口层可以使用平台定义(platform-defined)的类型，如果同时提供了针对这些类型的操作
    \footnote{ZhangDi：原文-Strong HILs may use platform-defined types if 
	      they also provide operations to manipulate them.
	      谁能告诉我这里的they指代谁？根据下文“抽象数据类型”，似乎应当指代“平台”。}
    （比如平台定义的抽象数据类型）。如TinyOS2.x的消息缓冲区抽象message\_t[TEP111]。
    \footnote{ZhangDi：给国内电子类专业的学生（不出意外，你们的知识体系里应该没有这个概念）：
	      所谓“抽象数据类型”，其最重要一特点是在提供数据结构的同时提供对该结构的操作函数，
	      从而达到屏蔽数据的实现细节的目的。比如C语言的FILE*类型，同时提供针对文件的
	      多种操作函数如fopen/fwrite等，使得你无须关心FILE*背后干了是什么事情}
  \subsection{弱硬件接口层}
    弱硬件接口层程序是便于移植的，其行为是针对某特定平台(platform-specific)的。
    但应用程序（至少是从语义上，不过需要获取平台相关的信息）可以是平台无关的。
    比如ADC抽象需要针对特定平台进行配置，且采集的数据需要根据这个配置进行解释。
    ADC的配置功能通过AdcConfigure接口提供给所有平台。
    这个接口使用一个平台定义的数据类型adc\_config\_t作为参数。
    但是ADC的返回数据可以用不依赖于具体平台的方式进行处理（比如求出返回值的最大最小值，或求平均值）。

    弱硬件接口层的好处是程序员可以编写容易移植的代码，例如一个在数据通路上连续采样的ADC。
    虽然使用这些抽象的代码也许不是完全兼容于各个平台的，但是它们比直接构建在HAL层上的代码有更好的移植性。
    因为弱平台接口层给出了一些便于移植的实现准则，这将有助于程序员编写容易移植的代码。
  \subsection{硬件无关接口}
    硬件无关接口（HII）的目的是提供一个跨平台的接口定义。TEP117中的SID接口和TEP102
    中的Alarm / Counter / etc接口是这样的硬件无关接口的例子。
  \subsection{工具组件}
    工具组件是小块的明确可以移植的代码（往往是泛型组件）。工具组件自身并不提供完整的服务。
    工具组件的范例是tos/lib/timer目录下的组件和ArbitratedRead*组件。它们提供和使用硬件无关接口。
\section{结论}
  这里提出的硬件抽象结构提供一个核心的服务集
  \footnote{ZhangDi：service这个词在TinyOS里经常出现，意思就是可以被上层应用调用的软件模块。}
  ，用来消除重复的代码，并且提供了跨平台的一致视图。
  这种结构支持在应用程序中同时使用平台无关的接口和平台相关的接口。
  在这种机制下，应用程序可以把平台相关的部分限制在那些性能受限的关键部分，
  与此同时别的部分使用跨平台的标准接口。
\section{作者地址}
  ......
\section{引用文献}
  ......
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{CJK}
\end{document}